﻿using System;
using System.Collections;

namespace ADTLists
{
    public class ADTIntArray : ADT
    {
        private int[] _dataStorage;

        public ADTIntArray()
        {
            size = 0;
            _dataStorage = new int[0];
        }

        public override object GetElementFromStart()
        {
            if (_dataStorage != null && size > 0)
            {
                return _dataStorage[0];
            }
            throw new Exception("Error while getting the 1st element");
        }

        public override object GetElementFromEnd()
        {
            if (_dataStorage != null && size > 0)
            {
                return _dataStorage[size - 1];
            }
            throw new Exception("Error while getting the last element");
        }

        public override object GetElementFromPosition(int position)
        {
            if (_dataStorage != null && size >= position && size > 0)
                return _dataStorage[position];
            throw new Exception("Error while getting the element #" + position);
        }

        public override void DelFromStart()
        {
            if (_dataStorage != null && size > 0)
            {
                size--;
                int[] tempDataStorage = _dataStorage;
                _dataStorage = new int[size];
                Array.Copy(tempDataStorage, 1, _dataStorage, 0, size);
            }
            else
            {
                throw new Exception("Error while deleting the 1st element");
            }
        }

        public override void DelFromEnd()
        {
            if (_dataStorage != null && size > 0)
            {
                size--;
                int[] tempDataStorage = _dataStorage;
                _dataStorage = new int[size];
                Array.Copy(tempDataStorage, 0, _dataStorage, 0, size);
            }
            else
            {
                throw new Exception("Error while deleting the last element");
            }
        }

        public override void DelFromPosition(int position)
        {
            if (_dataStorage != null && position < size && size > 0)
            {
                size--;
                var tempDataStorageBefore = new int[position];
                var tempDataStorageAfter = new int[size - position - 1];
                Array.Copy(_dataStorage, 0, tempDataStorageBefore, 0, position);
                Array.Copy(_dataStorage, position + 1, tempDataStorageAfter, 0, size - position - 2);
                _dataStorage = new int[size];
                Array.Copy(tempDataStorageBefore, 0, _dataStorage, 0, tempDataStorageBefore.Length);
                Array.Copy(tempDataStorageAfter, 0, _dataStorage, position + 1, tempDataStorageAfter.Length);
            }
            else
            {
                throw new Exception("Error while deleting the element #" + position);
            }
        }

        public override void AddToStart(object element)
        {
            if (_dataStorage != null && size >= 0)
            {
                if ((size + 1)> int.MaxValue)
                {
                    throw new Exception("Can't add new element: maximum size reached");
                }
                size++;
                int[] tempDataStorage = _dataStorage;
                _dataStorage = new int[size];
                tempDataStorage.CopyTo(_dataStorage, 1);
                _dataStorage[0] = (int)element;
            }
            else
            {
                throw new Exception("Error while adding the 1st element");
            }
        }

        public override void AddToEnd(object element)
        {
            if (_dataStorage != null && size >= 0)
            {
                if ((size + 1) > int.MaxValue)
                {
                    throw new Exception("Can't add new element: maximum size reached");
                }
                size++;
                int[] tempDataStorage = _dataStorage;
                _dataStorage = new int[size];
                tempDataStorage.CopyTo(_dataStorage, 0);
                _dataStorage[size - 1] = (int)element;
            }
            else
            {
                throw new Exception("Error while adding the last element");
            }
        }

        public override void AddToPosition(object element, int position)
        {
            if (_dataStorage != null && size >= 0)
            {
                if ((size + 1) > int.MaxValue)
                {
                    throw new Exception("Can't add new element: maximum size reached");
                }
                if (position >= size)
                {
                    size = position + 1;
                    var temp = _dataStorage;
                    _dataStorage = new int[size];
                    Array.Copy(temp, 0, _dataStorage, 0, temp.Length);
                    _dataStorage[position] = (int)element;
                    return;
                }
                size++;
                var tempDataStorageBefore = new int[position];
                var tempDataStorageAfter = new int[size - position - 1];
                Array.Copy(_dataStorage, 0, tempDataStorageBefore, 0, position);
                Array.Copy(_dataStorage, position, tempDataStorageAfter, 0, size - position - 1);
                _dataStorage = new int[size];
                Array.Copy(tempDataStorageBefore, 0, _dataStorage, 0, tempDataStorageBefore.Length);
                Array.Copy(tempDataStorageAfter, 0, _dataStorage, position + 1, tempDataStorageAfter.Length);
                _dataStorage[position] = (int)element;
            }
            else
            {
                throw new Exception("Error while adding the element #" + position);
            }
        }

        public override void SetFirst(object element)
        {
            if (size > 0 && _dataStorage != null)
            {
                _dataStorage[0] = (int)element;
            }
            else
            {
                throw new Exception("Error while setting the 1st element");
            }
        }

        public override void SetLast(object element)
        {
            if (size > 0 && _dataStorage != null)
            {
                _dataStorage[size - 1] = (int)element;
            }
            else
            {
                throw new Exception("Error while setting the last element");
            }
        }

        public override void SetToPosition(object element, int position)
        {
            if (size > 0 && _dataStorage != null && position < size)
            {
                _dataStorage[position] = (int)element;
            }
            else
            {
                throw new Exception("Error while setting the element #" + position);
            }
        }

        public override void Clear()
        {
            size = 0;
            _dataStorage = new int[0];
        }

        public override IEnumerator GetEnumerator()
        {
            return _dataStorage.GetEnumerator();
        }
    }
}
